<?php

/**
 * Custom loader class.
 *
 * @author		Tamás Kovács <kovacs.tamas.hun@gmail.com>
 * @copyright	Tamás Kovács <kovacs.tamas.hun@gmail.com>
 * @package		default
 */

require_once 'Zend/Loader.php';

/**
 * Smithy_Loader
 *
 * @package Smithy
 * @author Tamás Kovács <kovacs.tamas.hun@gmail.com>
 * @copyright Tamás Kovács <kovacs.tamas.hun@gmail.com>
 * @version 1.0
 * @access public
 */
class Smithy_Loader extends Zend_Loader
{
    /**
     * @var Zend_Loader_PluginLoader
     */
    protected static $_pluginloader = NULL;

    /**
     * The applications prefix.
     */
    protected static $_applicationPrefix = '';

    /**
     * Smithy_Loader::loadClass()
     *
     * @see Zend_Loader::loadClass()
     * @param mixed $class
     * @param mixed $dirs
     * @return void
     */
    public static function loadClass($class, $dirs = NULL, $moduleName = NULL)
    {
        try {
            @parent::loadClass($class, $dirs);
        } catch (Exception $e) {
            $class = str_replace(self::_getCurrentPrefix($moduleName), '', $class);
            self::_getPluginLoader(ucfirst($moduleName))->load($class);
        }
    }

    /**
     * Loads a model resource.
     *
     * @param string $resourceName  The name of the resource without the
                                    module and the application prefix.
     * @param string $resourceType  The type of the resource. Possible values:
                                    Form, DbTable, Service etc.
                                    NOTE: This method will not check if the type
                                    is an existing directory or not.
     * @param string $moduleName    The name of the module the resource is
                                    located in. [OPTIONAL]
     * @return string The name of the loaded class.
     * @throws Zend_Loader_Exception If the resource is not found.
     */
    public static function loadResource($resourceName, $resourceType = '', $moduleName = null)
    {
        $front = Zend_Controller_Front::getInstance();

        $resourceName = '' === $resourceType ? $resourceName : $resourceType . '_' . $resourceName;
    	if (null === $moduleName) {
    	    $moduleName = $front->getDispatcher()->getDefaultModule();
    	}
    	$modelDir = dirname($front->getControllerDirectory(strtolower($moduleName))) . '/models';
    	$className = self::$_applicationPrefix
    	   . (null === $moduleName ? '' : $moduleName . '_')
    	   . $resourceName;

        self::loadClass($className, $modelDir, $moduleName);
        return $className;
    }

    /**
     * Returns with the pluginloader, with the apropiate prefixes and paths.
     *
     * @param string $moduleName
     * @return Zend_Loader_PluginLoader
     */
    protected static function _getPluginLoader($moduleName = null)
    {
        $front = Zend_Controller_Front::getInstance();
        $request = $front->getRequest();
        $moduleName = empty($moduleName) ? $request->getModuleName() : ucfirst($moduleName);

        if (empty($moduleName)) {
            $moduleName = $front->getDispatcher()->getDefaultModule();
        }

        $moduleDirectory = $front->getControllerDirectory(strtolower($moduleName));
        $modelsDirectory = dirname($moduleDirectory) . '/models';

        if (NULL === self::$_pluginloader) {
            self::$_pluginloader = new Zend_Loader_PluginLoader();
        }

        self::$_pluginloader->addPrefixPath($moduleName, $modelsDirectory);
        return self::$_pluginloader;
    }

    /**
     * Smithy_Loader::autoload()
     *
     * @see Zend_Loader::autoload()
     * @param mixed $class
     * @return
     */
    public static function autoload($class)
    {
        try {
            self::loadClass($class);
            return $class;
        } catch (Exception $e) {
            try {
                return self::_getPluginLoader()->load($class);
            } catch (Zend_Loader_Exception $e) {
                return false;
            }
        }
    }

    /**
     * Sets the application wide prefix.
     *
     * @param string $prefix
     * @return void
     */
    public static function setApplicationPrefix($prefix)
    {
    	self::$_applicationPrefix = $prefix . '_';
    }

    /**
     * @return string
     */
    protected static function _getCurrentPrefix($moduleName = null)
    {
        $front = Zend_Controller_Front::getInstance();
        $request = $front->getRequest();
        $moduleName = empty($moduleName) ? $request->getModuleName() : ucfirst($moduleName);

        if (empty($moduleName)) {
            $moduleName = $front->getDispatcher()->getDefaultModule();
        }

        $prefix = self::$_applicationPrefix . (('default' == $moduleName) ? '' : ucfirst($moduleName) . '_');

        return $prefix;
    }
}
